package com.tsmti.util;


import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;
import com.tsmti.core.common.constant.Constants;
import com.tsmti.core.common.constant.RedisConstants;
import com.tsmti.core.util.*;
import com.tsmti.system.entity.Menu;
import com.tsmti.system.entity.Principal;
import com.tsmti.system.entity.Role;
import com.tsmti.system.entity.User;
import com.tsmti.system.service.MenuService;
import com.tsmti.system.service.RoleService;
import com.tsmti.system.service.UserService;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Title：PimsSystem
 * Class：com.ts.sys.shiro.realm
 * Comapny:
 *
 * @author：zcw
 * @version：2.5 CreateTime：2018/1/17 14:36
 * Modify log:
 * Description：
 * 用户工具类
 */
@SuppressWarnings("unchecked")
public class UserUtils {
	private static Logger logger = Logger.getLogger(UserUtils.class);
	private static UserService userService = SpringContextUtils.getBean(UserService.class);
	private static RoleService roleService = SpringContextUtils.getBean(RoleService.class);
	private static MenuService menuService = SpringContextUtils.getBean(MenuService.class);
	public static final String USER_CACHE_ID_ = "id_";

	public static final String USER_CACHE_USER_NAME_ = "username_";

	public static final String MENU_CACHE_URL_ = "menu_url_";

	public static final String CACHE_ROLE_LIST = "roleCache";

	public static final String CACHE_MENU_LIST = "menuCache_";
	/**
	 * 根据ID获取用户
	 * 
	 * @param id
	 * @return 取不到返回null
	 */
	public static User get(long id) {
		User user = (User) CacheUtils.get(RedisConstants.USER_CACHE, USER_CACHE_ID_ + id);

		if (user == null) {
			user = userService.get(id);
			if (user == null) {
				return null;
			}
			CacheUtils.put(RedisConstants.USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(RedisConstants.USER_CACHE, USER_CACHE_USER_NAME_ + user.getUserName(), user);
		}
		return user;
	}

	/**
	 * 根据用户名获取用户
	 * 
	 * @param username
	 * @return
	 */
	public static User getByUserName(String username) {
		User user = (User) CacheUtils.get(RedisConstants.USER_CACHE, USER_CACHE_USER_NAME_ + username);
		if (user == null) {
			user = userService.findByUsername(username);
			if (user == null) {
				return null;
			}
			CacheUtils.put(RedisConstants.USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(RedisConstants.USER_CACHE, USER_CACHE_USER_NAME_ + user.getUserName(), user);
		}
		return user;
	}

	/**
	 * 清除当前用户缓存
	 */
	public static void clearCache() {
		removeCache(CACHE_ROLE_LIST);
		removeCache(CACHE_MENU_LIST);
		UserUtils.clearCache(getUser());
	}

	/**
	 * 清除指定用户缓存
	 * 
	 * @param user
	 */
	public static void clearCache(User user) {
		CacheUtils.remove(RedisConstants.USER_CACHE, USER_CACHE_ID_ + user.getId());
		CacheUtils.remove(RedisConstants.USER_CACHE, USER_CACHE_USER_NAME_ + user.getUserName());
	}

	/**
	 * 获取当前用户
	 * 
	 * @return 取不到返回 new User()
	 */
	public static User getUser() {
		Principal principal = getPrincipal();
		if (principal != null) {
			User user = get(principal.getId());
			if (user != null) {
				return user;
			}
			return null;
		}
		// 如果没有登录，则返回实例化空的User对象。
		return null;
	}

	/**
	 * 当前用户名
	 * @return
	 */
	public static String getUserName() {
		String userName = "";
		Principal principal = getPrincipal();
		if (principal != null) {
			User user = get(principal.getId());
			if (user != null) {
				userName =  user.getUserName();
			}
		}
		// 如果没有登录，则返回实例化空的User对象。
		return userName;
	}

	/**
	 * 当前登陆用户机构ID
	 * @return
	 */
	public static String getOrgId() {
		Principal principal = getPrincipal();
		String orgId = "";
		if( principal != null){
			if(principal.getOrgId()!=null){
				orgId = ConvertUtil.null2String(principal.getOrgId());
			}
		}
		return orgId;
	}

	public static String getRealName(String userName){
		String realName = "";
		User user = (User) CacheUtils.get(RedisConstants.USER_CACHE, USER_CACHE_USER_NAME_ + userName);
		if(null!=user){
			realName = ConvertUtil.null2String(user.getRealName());
		}
		return realName;
	}

	/**
	 * 当前用户ID
	 * @return
	 */
	public static Long getUserId() {
		Long userId = null;
		Principal principal = getPrincipal();
		if (principal != null) {
			User user = get(principal.getId());
			if (user != null) {
				userId =  user.getId();
			}
		}
		// 如果没有登录，则返回实例化空的User对象。
		return userId;
	}
	/**
	 * 获取当前用户角色列表
	 * 
	 * @return
	 */
	public static List<Role> getRoleList() {
		List<Role> roleList = (List<Role>) getCache(CACHE_ROLE_LIST);
		if (roleList == null) {
			User user = getUser();
			roleList = roleService.findListByUserId(user.getId());
			putCache(CACHE_ROLE_LIST, roleList);
		}
		return roleList;
	}

	public static Set<String> getRoleStringList() {
		Set<Role> roles = Sets.newConcurrentHashSet(getRoleList());
		return Sets.newHashSet(Collections2.transform(roles, new Function<Role, String>() {
			@Override
			public String apply(Role role) {
				return role.getCode();
			}
		}));
	}

	/**
	 * 获取当前用户授权菜单
	 * 
	 * @return
	 */
	public static List<Menu> getMenuList() {
		Long userId = getUserId();
		List<Menu> menuList = (List<Menu>) getCache(CACHE_MENU_LIST+userId);
		if (menuList == null) {
			menuList = menuService.findMenuByUserId(userId);
			putCache(CACHE_MENU_LIST+userId, menuList);
		}
		return menuList;
	}

	/**
	 * 获取临床医生或护理端菜单
	 *
	 * @return
	 */
	public static List<Menu> getMenuList(Long userId) {
		List<Menu> menuList = (List<Menu>) getCache(CACHE_MENU_LIST+userId);
		if (menuList == null) {
			menuList = menuService.findMenuByUserId(userId);
			putCache(CACHE_MENU_LIST+userId, menuList);
		}
		return menuList;
	}

	/**
	 * 获取当前菜单
	 * 
	 * @return
	 */
	public static Menu getCurrentMenu() {
		String url = AbstractServletUtils.getRequest().getServletPath();
		if (url.endsWith(Constants.JSP)) {
			return null;
		}
		url = StringUtils.trimFirstAndLastChar(url, Constants.SLASHCHAR);
		if (StringUtils.isEmpty(url)) {
			return null;
		}
		// 全匹配查找
		List<Menu> menuList = getMenuList();
		return getCurrentMenu(menuList, url);
	}

	private static Menu getCurrentMenu(List<Menu> menuList, String url) {
		for (Menu menu : menuList) {
			if (!StringUtils.isEmpty(menu.getUrl())
					&& url.equals(StringUtils.trimFirstAndLastChar(menu.getUrl(), '/'))) {
				return menu;
			}
		}
		return null;
	}

	/**
	 * 通过ID获得菜单信息
	 * 
	 * @return
	 */
	public static Menu getMenuById(String menuid) {
		if (StringUtils.isEmpty(menuid)) {
			return null;
		}
		List<Menu> menuList = getMenuList();
		for (Menu menu : menuList) {
			if (menuid.equals(menu.getId())) {
				return menu;
			}
		}
		return null;
	}

	public static Set<String> getPermissionsList() {
		List<Menu> list = UserUtils.getMenuList();
		Set<String> permissionsList = Sets.newConcurrentHashSet();
		for (Menu menu : list) {
			if (StringUtils.isNotBlank(menu.getPermission())) {
				// 添加基于Permission的权限信息
				for (String permission : StringUtils.split(menu.getPermission(), Constants.COMMA)) {
					if (StringUtils.isNotBlank(permission)) {
						permissionsList.add(permission);
					}
				}
			}
		}
		return permissionsList;
	}

	/**
	 * 获取当前用户授权菜单
	 * 
	 * @return
	 */
	public static Menu getTopMenu() {
		Menu topMenu = getMenuList().get(0);
		return topMenu;
	}

	/**
	 * 获取授权主要对象
	 */
	public static Subject getSubject() {
		return SecurityUtils.getSubject();
	}

	/**
	 * 获取当前登录者对象
	 */
	public static Principal getPrincipal() {
		try {
			Subject subject = SecurityUtils.getSubject();
			Principal principal = (Principal) subject.getPrincipal();
			if (principal != null) {
				return principal;
			}
		} catch (UnavailableSecurityManagerException e) {
			logger.error(e);
		} catch (InvalidSessionException e) {
			logger.error(e);
		}
		return null;
	}

	public static Session getSession() {
		try {
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(false);
			if (session == null) {
				session = subject.getSession();
			}
			if (session != null) {
				return session;
			}
		} catch (InvalidSessionException e) {
			logger.error(e);
		}
		return null;
	}

	/**
	 * 用户缓存
	 * @param key
	 * @return
	 */
	public static Object getCache(String key) {
		return getCache(key, null);
	}

	public static Object getCache(String key, Object defaultValue) {
		Object obj = getSession().getAttribute(key);
		return obj == null ? defaultValue : obj;
	}

	public static void putCache(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
		getSession().removeAttribute(key);
	}


	/**
	 * 添加user的密码加密方法
	 * @param user
	 * @return
	 */
	public static boolean  checkPassword(User user,String password) {
		//加密方式
		String algorithmName = "MD5";
		//密码原值
		Object oldPassword =user.getPassword();
		//加密2次
		int hashIterations = 2;
		String newPassword = new SimpleHash(algorithmName, password,
				ByteSource.Util.bytes(user.getCredentialsSalt()), hashIterations).toHex();
		boolean flag = oldPassword.equals(newPassword);
		return flag;
	}

	/**
	 * 重载用户缓存
	 */
	public static void reLoadCache(){
		List<User> userList = userService.list();
		List<User> phyUserList = userService.list("userJobType",1);
		List<User> tecUserList = userService.list("userJobType",2);
		RedisUtils.setRedisToMap(RedisConstants.USER_CACHE,"userName", userList);
		RedisUtils.setRedisToMap(RedisConstants.PHY_USER_CACHE,"userName", phyUserList);
		RedisUtils.setRedisToMap(RedisConstants.TEC_USER_CACHE,"userName", tecUserList);
	}
	/**
	 * 加载用户缓存
	 */
	public static Map<String, User> loadUserCache() {
		Map<String, User> userMap = new HashMap<String, User>(16);
		try {
			userMap = (Map<String, User>) RedisUtils.getObject(RedisConstants.USER_CACHE);
		} catch (Exception e) {
			logger.warn("读取缓存失败!");
			e.printStackTrace();
		}
		if (userMap == null || userMap.size() <= 0) {
			List<User> userList = userService.list();
			try {
				RedisUtils.setRedisToMap(RedisConstants.USER_CACHE,"userName", userList);
			} catch (Exception e) {
				logger.warn("加载缓存错误!", e);
			}
		}
		return userMap;
	}
	/**
	 * 病理医师缓存
	 */
	public static Map<String, User> loadPhyUserCache() {
		Map<String, User> phyUserMap = new HashMap<String, User>(16);
		try {
			phyUserMap = (Map<String, User>) RedisUtils.getObject(RedisConstants.PHY_USER_CACHE);
		} catch (Exception e) {
			logger.warn("读取缓存失败!");
			e.printStackTrace();
		}
		if (phyUserMap == null || phyUserMap.size() <= 0) {
			List<User> phyUserList = userService.list("userJobType",1);
			try {
				RedisUtils.setRedisToMap(RedisConstants.PHY_USER_CACHE,"userName", phyUserList);
			} catch (Exception e) {
				logger.warn("加载缓存错误!", e);
			}
		}
		return phyUserMap;
	}
	/**
	 * 病理技师缓存
	 */
	public static Map<String, User> loadTecUserCache() {
		Map<String, User> tecUserMap = new HashMap<String, User>(16);
		try {
			tecUserMap = (Map<String, User>) RedisUtils.getObject(RedisConstants.TEC_USER_CACHE);
		} catch (Exception e) {
			logger.warn("读取缓存失败!");
			e.printStackTrace();
		}
		if (tecUserMap == null || tecUserMap.size() <= 0) {
			List<User> tecUserList = userService.list("userJobType",2);
			try {
				RedisUtils.setRedisToMap(RedisConstants.TEC_USER_CACHE,"userName", tecUserList);
			} catch (Exception e) {
				logger.warn("加载缓存错误!", e);
			}
		}
		return  tecUserMap;
	}

}
